package com.happy.people.service.impl;


import com.happy.people.service.BaseService;
import org.beetl.sql.core.*;
import org.beetl.sql.core.db.*;
import org.beetl.sql.core.engine.PageQuery;
import org.beetl.sql.core.query.Query;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import static org.beetl.sql.core.BeetlSQLException.SQL_EXCEPTION;

/**
 * @Author : Yan
 * @Description : BaseService Impl class
 */
public class BaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    private SQLManager sqlManager;

    // create genericity T is super Class --> clazz
    Class<T> clazz;

    {
        // 使用反射技术得到T的真实类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型
        clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/19
     * @Description :  find this table All date list
     */
    @Override
    public List<T> find_All() {
        return sqlManager.all(clazz);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/19
     * @Description :  find this table all data list size
     */
    @Override
    public long find_All_Size() {
        return sqlManager.allCount(clazz);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/19
     * @Description :  find this table data by primary key
     */
    @Override
    public T find_ObjByPK(int pk) {
        return sqlManager.single(clazz, pk);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :   find this table data by where params
     */
    @Override
    public T find_ObjByWhere(Object params) {
        List<T> list = sqlManager.template(clazz, params, null);
        if (list != null && list.size() > 0) {
            if (list.size() == 1) {
                return list.get(0);
            }
            throw new BeetlSQLException(SQL_EXCEPTION, "本应查询1条数据，但查出:" + list.size() + "条!");
        }
        return null;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/19
     * @Description :  find this table data by where params , this params best Map<String,Object> ;but this data list is disorder
     */
    @Override
    public List<T> find_ListByWhere(Object params) {
        List<T> list = sqlManager.template(clazz, params, null);
        if (list != null && list.size() > 0)
            return list;
        return null;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  find this table data by where params , this params best Map<String,Object> ; but this data list is disorder and limit size
     */
    @Override
    public List<T> find_ListByWhere(Object params, long start, long size) {
        List<T> list = sqlManager.template(clazz, params, start, size);
        if (list != null && list.size() > 0)
            return list;
        return null;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  find this table data by where params , this params best Map<String,Object> ; but this data list is order
     */
    @Override
    public List<T> find_ListByWhere(Object params, String orderBy) {
        List<T> list = sqlManager.template(clazz, params, orderBy);
        if (list != null && list.size() > 0)
            return list;
        return null;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  find this table data by where params , this params best Map<String,Object> ; but this data list is order and limit size
     */
    @Override
    public List<T> find_ListByWhere(Object params, long start, long size, String orderBy) {
        List<T> list = sqlManager.template(clazz, params, start, size, orderBy);
        if (list != null && list.size() > 0)
            return list;
        return null;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/19
     * @Description :  find this table data by where params size , this params best Map<String,Object>
     */
    @Override
    public long find_ListByWhere_Size(Object params) {
        return sqlManager.templateCount(clazz, params);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  insert data into this table , include if field is null insert , return primary key
     */
    @Override
    public int insert(T params) {
        KeyHolder holder = new KeyHolder();
        sqlManager.insert(clazz, params, holder);
        return holder.getInt();
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  insert data into this table , include if field is null no insert , return primary key
     */
    @Override
    public int insert_Selective(Object params) {
        KeyHolder holder = new KeyHolder();
        sqlManager.insertTemplate(clazz, params, holder);
        return holder.getInt();
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  insert batch data list into this table , return insert success length
     */
    @Override
    public int insert_Batch(List<T> list) {
        return sqlManager.insertBatch(clazz, list).length;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description : update data into this table by pk, include if field is null update , return update size
     */
    @Override
    public int update_ByPK(T params) {
        return sqlManager.updateById(params);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description : update data into this table by pk, include if field is null no update , return update size
     */
    @Override
    public int update_Selective_ByPK(Object params) {
        return sqlManager.updateTemplateById(clazz, params);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  update batch data list into this table , if field is null update , return insert success length
     */
    @Override
    public int update_Batch_ByPK(List<T> list) {
        return sqlManager.updateByIdBatch(list).length;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  update batch data list into this table , if field is null no update , return insert success length
     */
    @Override
    public int update_BatchSelective_ByPK(List<?> list) {
        return sqlManager.updateBatchTemplateById(clazz, list).length;
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description : delete this table by primary key , return delete success length
     */
    @Override
    public int delete_ByPK(Object pkValue) {
        return sqlManager.deleteById(clazz, pkValue);
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/21
     * @Description : delete this table by primary key Array , return delete success length
     */
    @Override
    public int delete_ByPKArray(String[] PkArray) {
        List<String> PKList = Arrays.asList(PkArray);
        // find primary key column
        String PK_Column = "";
        NameConversion nameConversion = sqlManager.getDbStyle().getNameConversion();
        String tableName = nameConversion.getTableName(clazz);
        TableDesc table = sqlManager.getMetaDataManager().getTable(tableName);
        ClassDesc classDesc = table.getClassDesc(clazz, nameConversion);
        List<String> colIds = classDesc.getIdCols();
        List<String> propertieIds = classDesc.getIdAttrs();
        if (colIds.size() == 0 || propertieIds.size() == 0) {
            throw new BeetlSQLException(BeetlSQLException.ID_NOT_FOUND, "主键未发现," + clazz.getName() + ",检查数据库表定义或者NameConversion");
        }
        KeyWordHandler keyWordHandler = new DefaultKeyWordHandler();
        Iterator<String> colIt = colIds.iterator();
        Iterator<String> propertieIt = propertieIds.iterator();
        if (colIt.hasNext() && propertieIt.hasNext()) {
            String colId = colIt.next();
            PK_Column = keyWordHandler.getCol(colId);
            System.out.print(PK_Column + "---------------");
            while (colIt.hasNext() && propertieIt.hasNext()) {
                colId = colIt.next();
                PK_Column = keyWordHandler.getCol(colId);
                System.out.print(PK_Column + "++++++++++++++");
            }
        }
        Query<T> query = sqlManager.query(clazz);
        return query.andIn(PK_Column, PKList).delete();
    }

    /**
     * @Author : Yan
     * @Create : 2019/12/20
     * @Description :  find this table page limit date , PageQuery{ paras:参数; orderBy:排序; pageNumber:页数; pageSize:每页记录数; totalPage:总页数; totalRow:总行数 }
     */
    @Override
    public PageQuery<T> find_Page(PageQuery pageQuery) {
        long start = (pageQuery.getPageNumber() - 1) * pageQuery.getPageSize();
        List<T> list = sqlManager.template(clazz, pageQuery.getParas(), start, pageQuery.getPageSize(), pageQuery.getOrderBy());
        long totalRow = sqlManager.templateCount(clazz, pageQuery.getParas());
        pageQuery.setList(list);
        pageQuery.setTotalRow(totalRow);
        pageQuery.getTotalPage();
        return pageQuery;
    }

}
